package net.zoneland.zrdp.common.filter;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Optional;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import com.fasterxml.jackson.databind.JsonNode;
import net.zoneland.zrdp.common.utils.JacksonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import net.zoneland.zrdp.common.utils.html.EscapeUtil;


/**
 * XSS过滤处理
 *
 * @author zonevue
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
    /**
     * @param request 请求request
     */
    public XssHttpServletRequestWrapper(final HttpServletRequest request) {
        super(request);
    }

    @Override
    public String[] getParameterValues(final String name) {
        final String[] values = super.getParameterValues(name);
        return Optional.ofNullable(values)
            .map(arr -> Arrays.stream(arr)
                .map(EscapeUtil::cleanXss)
                .toArray(String[]::new))
            .orElse(values);
    }
    @Override
    public String getParameter(final String parameter) {
        return Optional
            .ofNullable(super.getParameter(parameter))
            .filter(StringUtils::isNotBlank)
            .map(EscapeUtil::cleanXss)
            .orElse(null);
    }

    @Override
    public String getHeader(final String name) {
        return Optional
            .ofNullable(super.getHeader(name))
            .filter(StringUtils::isNotBlank)
            .map(EscapeUtil::cleanXss)
            .orElse(null);
    }
    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ServletInputStream inputStream = super.getInputStream();
        // 如果不是json请求或者input流为空，直接返回
        if (!isJsonRequest()) {
            return inputStream;
        }

        // XSS 过滤
        final JsonNode jsonNode = JacksonUtils.toJsonNode(inputStream);
        final JsonNode saftJsonNode = EscapeUtil.jsonCleanXss(jsonNode, JacksonUtils.getObjectMapper());
        final String safeJson = JacksonUtils.toString(saftJsonNode);
        final byte[] jsonBytes = safeJson.getBytes(StandardCharsets.UTF_8);
        final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);

        // 创建 ServletInputStream
        return new RepeatedlyServletInputStream(bis, jsonBytes.length);

    }


    /**
     * 是否是Json请求
     *
     */
    public boolean isJsonRequest() {
        final String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
    }
}
